/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ws.service;

import entidade.persistencia.Produto;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.DELETE;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.QueryParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import com.sun.jersey.api.core.ResourceContext;
import javax.ws.rs.WebApplicationException;
import javax.persistence.NoResultException;
import javax.persistence.EntityManager;
import entidade.persistencia.ProdutoVenda;
import entidade.persistencia.ProdutoManutencao;
import entidade.persistencia.ProdutoCompra;
import entidade.persistencia.ReparoProdutoNumeroSerie;
import entidade.persistencia.ProdutoNumeroSerie;
import entidade.persistencia.CategoriaProduto;
import java.util.List;
import ws.converter.ProdutoConverter;

/**
 *
 * @author victorinox
 */

public class ProdutoResource {
    @Context
    protected UriInfo uriInfo;
    @Context
    protected ResourceContext resourceContext;
    protected Integer id;
  
    /** Creates a new instance of ProdutoResource */
    public ProdutoResource() {
    }

    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * Get method for retrieving an instance of Produto identified by id in XML format.
     *
     * @param id identifier for the entity
     * @return an instance of ProdutoConverter
     */
    @GET
    @Produces({"application/xml", "application/json"})
    public ProdutoConverter get(@QueryParam("expandLevel")
    @DefaultValue("1")
    int expandLevel) {
        PersistenceService persistenceSvc = PersistenceService.getInstance();
        try {
            persistenceSvc.beginTx();
            return new ProdutoConverter(getEntity(), uriInfo.getAbsolutePath(), expandLevel);
        } finally {
            PersistenceService.getInstance().close();
        }
    }

    /**
     * Put method for updating an instance of Produto identified by id using XML as the input format.
     *
     * @param id identifier for the entity
     * @param data an ProdutoConverter entity that is deserialized from a XML stream
     */
    @PUT
    @Consumes({"application/xml", "application/json"})
    public void put(ProdutoConverter data) {
        PersistenceService persistenceSvc = PersistenceService.getInstance();
        try {
            persistenceSvc.beginTx();
            EntityManager em = persistenceSvc.getEntityManager();
            updateEntity(getEntity(), data.resolveEntity(em));
            persistenceSvc.commitTx();
        } finally {
            persistenceSvc.close();
        }
    }

    /**
     * Delete method for deleting an instance of Produto identified by id.
     *
     * @param id identifier for the entity
     */
    @DELETE
    public void delete() {
        PersistenceService persistenceSvc = PersistenceService.getInstance();
        try {
            persistenceSvc.beginTx();
            deleteEntity(getEntity());
            persistenceSvc.commitTx();
        } finally {
            persistenceSvc.close();
        }
    }

    /**
     * Returns an instance of Produto identified by id.
     *
     * @param id identifier for the entity
     * @return an instance of Produto
     */
    protected Produto getEntity() {
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        try {
            return (Produto) em.createQuery("SELECT e FROM Produto e where e.produtoId = :produtoId").setParameter("produtoId", id).getSingleResult();
        } catch (NoResultException ex) {
            throw new WebApplicationException(new Throwable("Resource for " + uriInfo.getAbsolutePath() + " does not exist."), 404);
        }
    }

    /**
     * Updates entity using data from newEntity.
     *
     * @param entity the entity to update
     * @param newEntity the entity containing the new data
     * @return the updated entity
     */
    protected Produto updateEntity(Produto entity, Produto newEntity) {
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        List<ProdutoNumeroSerie> produtoNumeroSerieCollection = entity.getProdutoNumeroSerieCollection();
        List<ProdutoNumeroSerie> produtoNumeroSerieCollectionNew = newEntity.getProdutoNumeroSerieCollection();
        CategoriaProduto categoriaId = entity.getCategoriaId();
        CategoriaProduto categoriaIdNew = newEntity.getCategoriaId();
        List<ProdutoVenda> produtoVendaCollection = entity.getProdutoVendaCollection();
        List<ProdutoVenda> produtoVendaCollectionNew = newEntity.getProdutoVendaCollection();
        List<ReparoProdutoNumeroSerie> reparoProdutoNumeroSerieCollection = entity.getReparoProdutoNumeroSerieCollection();
        List<ReparoProdutoNumeroSerie> reparoProdutoNumeroSerieCollectionNew = newEntity.getReparoProdutoNumeroSerieCollection();
        List<ProdutoManutencao> produtoManutencaoCollection = entity.getProdutoManutencaoCollection();
        List<ProdutoManutencao> produtoManutencaoCollectionNew = newEntity.getProdutoManutencaoCollection();
        List<ProdutoCompra> produtoCompraCollection = entity.getProdutoCompraCollection();
        List<ProdutoCompra> produtoCompraCollectionNew = newEntity.getProdutoCompraCollection();
        entity = em.merge(newEntity);
        for (ProdutoNumeroSerie value : produtoNumeroSerieCollection) {
            if (!produtoNumeroSerieCollectionNew.contains(value)) {
                throw new WebApplicationException(new Throwable("Cannot remove items from produtoNumeroSerieCollection"));
            }
        }
        for (ProdutoNumeroSerie value : produtoNumeroSerieCollectionNew) {
            if (!produtoNumeroSerieCollection.contains(value)) {
                Produto oldEntity = value.getProdutoId();
                value.setProdutoId(entity);
                if (oldEntity != null && !oldEntity.equals(entity)) {
                    oldEntity.getProdutoNumeroSerieCollection().remove(value);
                }
            }
        }
        if (categoriaId != null && !categoriaId.equals(categoriaIdNew)) {
            categoriaId.getProdutoCollection().remove(entity);
        }
        if (categoriaIdNew != null && !categoriaIdNew.equals(categoriaId)) {
            categoriaIdNew.getProdutoCollection().add(entity);
        }
        for (ProdutoVenda value : produtoVendaCollection) {
            if (!produtoVendaCollectionNew.contains(value)) {
                throw new WebApplicationException(new Throwable("Cannot remove items from produtoVendaCollection"));
            }
        }
        for (ProdutoVenda value : produtoVendaCollectionNew) {
            if (!produtoVendaCollection.contains(value)) {
                Produto oldEntity = value.getProduto();
                value.setProduto(entity);
                if (oldEntity != null && !oldEntity.equals(entity)) {
                    oldEntity.getProdutoVendaCollection().remove(value);
                }
            }
        }
        for (ReparoProdutoNumeroSerie value : reparoProdutoNumeroSerieCollection) {
            if (!reparoProdutoNumeroSerieCollectionNew.contains(value)) {
                throw new WebApplicationException(new Throwable("Cannot remove items from reparoProdutoNumeroSerieCollection"));
            }
        }
        for (ReparoProdutoNumeroSerie value : reparoProdutoNumeroSerieCollectionNew) {
            if (!reparoProdutoNumeroSerieCollection.contains(value)) {
                Produto oldEntity = value.getProdutoId();
                value.setProdutoId(entity);
                if (oldEntity != null && !oldEntity.equals(entity)) {
                    oldEntity.getReparoProdutoNumeroSerieCollection().remove(value);
                }
            }
        }
        for (ProdutoManutencao value : produtoManutencaoCollection) {
            if (!produtoManutencaoCollectionNew.contains(value)) {
                throw new WebApplicationException(new Throwable("Cannot remove items from produtoManutencaoCollection"));
            }
        }
        for (ProdutoManutencao value : produtoManutencaoCollectionNew) {
            if (!produtoManutencaoCollection.contains(value)) {
                Produto oldEntity = value.getProduto();
                value.setProduto(entity);
                if (oldEntity != null && !oldEntity.equals(entity)) {
                    oldEntity.getProdutoManutencaoCollection().remove(value);
                }
            }
        }
        for (ProdutoCompra value : produtoCompraCollection) {
            if (!produtoCompraCollectionNew.contains(value)) {
                throw new WebApplicationException(new Throwable("Cannot remove items from produtoCompraCollection"));
            }
        }
        for (ProdutoCompra value : produtoCompraCollectionNew) {
            if (!produtoCompraCollection.contains(value)) {
                Produto oldEntity = value.getProduto();
                value.setProduto(entity);
                if (oldEntity != null && !oldEntity.equals(entity)) {
                    oldEntity.getProdutoCompraCollection().remove(value);
                }
            }
        }
        return entity;
    }

    /**
     * Deletes the entity.
     *
     * @param entity the entity to deletle
     */
    protected void deleteEntity(Produto entity) {
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        if (!entity.getProdutoNumeroSerieCollection().isEmpty()) {
            throw new WebApplicationException(new Throwable("Cannot delete entity because produtoNumeroSerieCollection is not empty."));
        }
        CategoriaProduto categoriaId = entity.getCategoriaId();
        if (categoriaId != null) {
            categoriaId.getProdutoCollection().remove(entity);
        }
        if (!entity.getProdutoVendaCollection().isEmpty()) {
            throw new WebApplicationException(new Throwable("Cannot delete entity because produtoVendaCollection is not empty."));
        }
        if (!entity.getReparoProdutoNumeroSerieCollection().isEmpty()) {
            throw new WebApplicationException(new Throwable("Cannot delete entity because reparoProdutoNumeroSerieCollection is not empty."));
        }
        if (!entity.getProdutoManutencaoCollection().isEmpty()) {
            throw new WebApplicationException(new Throwable("Cannot delete entity because produtoManutencaoCollection is not empty."));
        }
        if (!entity.getProdutoCompraCollection().isEmpty()) {
            throw new WebApplicationException(new Throwable("Cannot delete entity because produtoCompraCollection is not empty."));
        }
        em.remove(entity);
    }

    /**
     * Returns a dynamic instance of ProdutoNumeroSeriesResource used for entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of ProdutoNumeroSeriesResource
     */
    @Path("produtoNumeroSerieCollection/")
    public ProdutoNumeroSeriesResource getProdutoNumeroSerieCollectionResource() {
        ProdutoNumeroSerieCollectionResourceSub resource = resourceContext.getResource(ProdutoNumeroSerieCollectionResourceSub.class);
        resource.setParent(getEntity());
        return resource;
    }

    /**
     * Returns a dynamic instance of CategoriaProdutoResource used for entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of CategoriaProdutoResource
     */
    @Path("categoriaId/")
    public CategoriaProdutoResource getCategoriaIdResource() {
        CategoriaIdResourceSub resource = resourceContext.getResource(CategoriaIdResourceSub.class);
        resource.setParent(getEntity());
        return resource;
    }

    /**
     * Returns a dynamic instance of ProdutoVendasResource used for entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of ProdutoVendasResource
     */
    @Path("produtoVendaCollection/")
    public ProdutoVendasResource getProdutoVendaCollectionResource() {
        ProdutoVendaCollectionResourceSub resource = resourceContext.getResource(ProdutoVendaCollectionResourceSub.class);
        resource.setParent(getEntity());
        return resource;
    }

    /**
     * Returns a dynamic instance of ReparoProdutoNumeroSeriesResource used for entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of ReparoProdutoNumeroSeriesResource
     */
    @Path("reparoProdutoNumeroSerieCollection/")
    public ReparoProdutoNumeroSeriesResource getReparoProdutoNumeroSerieCollectionResource() {
        ReparoProdutoNumeroSerieCollectionResourceSub resource = resourceContext.getResource(ReparoProdutoNumeroSerieCollectionResourceSub.class);
        resource.setParent(getEntity());
        return resource;
    }

    /**
     * Returns a dynamic instance of ProdutoManutencaoesResource used for entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of ProdutoManutencaoesResource
     */
    @Path("produtoManutencaoCollection/")
    public ProdutoManutencaoesResource getProdutoManutencaoCollectionResource() {
        ProdutoManutencaoCollectionResourceSub resource = resourceContext.getResource(ProdutoManutencaoCollectionResourceSub.class);
        resource.setParent(getEntity());
        return resource;
    }

    /**
     * Returns a dynamic instance of ProdutoComprasResource used for entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of ProdutoComprasResource
     */
    @Path("produtoCompraCollection/")
    public ProdutoComprasResource getProdutoCompraCollectionResource() {
        ProdutoCompraCollectionResourceSub resource = resourceContext.getResource(ProdutoCompraCollectionResourceSub.class);
        resource.setParent(getEntity());
        return resource;
    }

    public static class ProdutoNumeroSerieCollectionResourceSub extends ProdutoNumeroSeriesResource {

        private Produto parent;

        public void setParent(Produto parent) {
            this.parent = parent;
        }

        @Override
        protected List<ProdutoNumeroSerie> getEntities(int start, int max, String query) {
            List<ProdutoNumeroSerie> result = new java.util.ArrayList<ProdutoNumeroSerie>();
            int index = 0;
            for (ProdutoNumeroSerie e : parent.getProdutoNumeroSerieCollection()) {
                if (index >= start && (index - start) < max) {
                    result.add(e);
                }
                index++;
            }
            return result;
        }
    }

    public static class CategoriaIdResourceSub extends CategoriaProdutoResource {

        private Produto parent;

        public void setParent(Produto parent) {
            this.parent = parent;
        }

        @Override
        protected CategoriaProduto getEntity() {
            CategoriaProduto entity = parent.getCategoriaId();
            if (entity == null) {
                throw new WebApplicationException(new Throwable("Resource for " + uriInfo.getAbsolutePath() + " does not exist."), 404);
            }
            return entity;
        }
    }

    public static class ProdutoVendaCollectionResourceSub extends ProdutoVendasResource {

        private Produto parent;

        public void setParent(Produto parent) {
            this.parent = parent;
        }

        @Override
        protected List<ProdutoVenda> getEntities(int start, int max, String query) {
            List<ProdutoVenda> result = new java.util.ArrayList<ProdutoVenda>();
            int index = 0;
            for (ProdutoVenda e : parent.getProdutoVendaCollection()) {
                if (index >= start && (index - start) < max) {
                    result.add(e);
                }
                index++;
            }
            return result;
        }
    }

    public static class ReparoProdutoNumeroSerieCollectionResourceSub extends ReparoProdutoNumeroSeriesResource {

        private Produto parent;

        public void setParent(Produto parent) {
            this.parent = parent;
        }

        @Override
        protected List<ReparoProdutoNumeroSerie> getEntities(int start, int max, String query) {
            List<ReparoProdutoNumeroSerie> result = new java.util.ArrayList<ReparoProdutoNumeroSerie>();
            int index = 0;
            for (ReparoProdutoNumeroSerie e : parent.getReparoProdutoNumeroSerieCollection()) {
                if (index >= start && (index - start) < max) {
                    result.add(e);
                }
                index++;
            }
            return result;
        }
    }

    public static class ProdutoManutencaoCollectionResourceSub extends ProdutoManutencaoesResource {

        private Produto parent;

        public void setParent(Produto parent) {
            this.parent = parent;
        }

        @Override
        protected List<ProdutoManutencao> getEntities(int start, int max, String query) {
            List<ProdutoManutencao> result = new java.util.ArrayList<ProdutoManutencao>();
            int index = 0;
            for (ProdutoManutencao e : parent.getProdutoManutencaoCollection()) {
                if (index >= start && (index - start) < max) {
                    result.add(e);
                }
                index++;
            }
            return result;
        }
    }

    public static class ProdutoCompraCollectionResourceSub extends ProdutoComprasResource {

        private Produto parent;

        public void setParent(Produto parent) {
            this.parent = parent;
        }

        @Override
        protected List<ProdutoCompra> getEntities(int start, int max, String query) {
            List<ProdutoCompra> result = new java.util.ArrayList<ProdutoCompra>();
            int index = 0;
            for (ProdutoCompra e : parent.getProdutoCompraCollection()) {
                if (index >= start && (index - start) < max) {
                    result.add(e);
                }
                index++;
            }
            return result;
        }
    }
}
